home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / ae.lha / ae / AE / ae-mips.h < prev    next >
C/C++ Source or Header  |  1990-02-28  |  16KB  |  588 lines

  1. /* AE program profiling system.
  2.    Machine-specific definitions for MIPS R2000/R3000 processors.
  3.    Copyright (C) 1990 by James R. Larus (larus@cs.wisc.edu)
  4.  
  5.    AE and AEC are free software; you can redistribute it and/or modify it
  6.    under the terms of the GNU General Public License as published by the
  7.    Free Software Foundation; either version 1, or (at your option) any
  8.    later version.
  9.  
  10.    AE and AEC are distributed in the hope that it will be useful, but
  11.    WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.    General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with GNU CC; see the file COPYING.  If not, write to James R.
  17.    Larus, Computer Sciences Department, University of Wisconsin--Madison,
  18.    1210 West Dayton Street, Madison, WI 53706, USA or to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21.  
  22. /* $Header: /var/home/larus/AE/AE/RCS/ae-mips.h,v 2.0 90/02/09 17:21:37 larus Exp Locker: larus $ */
  23.  
  24.  
  25. /* Define the base and bounds of the AE buffer that accumulates events in
  26.    the executing program. */
  27.  
  28.  
  29. /* The pointer to the AE Buffer can either be in a register or in a
  30.    variable stored in memory.  If it is in a register, AE_BUFFER_REG
  31.    contains the register's name, as a string.  If it is in memory,
  32.    AE_BUFFER_VAR contains the variable's name as a string.
  33.    MAKE_AE_BUFFER_POINTER returns an rtx expression for this pointer. */
  34.  
  35.  
  36. /* On MIPS, we use R23 (aka) as the pointer to AE buffer.  The limit
  37.    is a fixed distance from the top of user memory, which is a negative
  38.    number. */
  39.  
  40. #define AE_BUFFER_REG "s7"
  41. #undef AE_BUFFER_VAR
  42.  
  43. #define MAKE_AE_BUFFER_POINTER() gen_rtx (REG, Pmode, 23) /* 23 = s7 */
  44.  
  45.  
  46. /* The end of the AE Buffer can either be pointed to by a register or
  47.    by a variable stored in memory.  If it is in a register,
  48.    AE_BUFFER_BOUND_REG contains the register's name, as a string.  If it
  49.    is in memory, AE_BUFFER_BOUND_VAR contains the variable's name as a
  50.    string.  MAKE_AE_BOUND_POINTER returns an rtx expression for this
  51.    pointer. */
  52.  
  53. #undef AE_BUFFER_BOUND_REG
  54. #undef AE_BUFFER_BOUND_VAR
  55.  
  56. #define MAKE_AE_BOUND_POINTER()
  57.  
  58.  
  59. /* Alternatively, the end of the AE buffer can be a fixed distance
  60.    from the top of the stack. */
  61.  
  62. /* Here's the picture for MIPS:
  63.  
  64.    Top of memory      --> @0x80000000
  65.    (Reserved on MIPS) -->  4K
  66.    Environemnt        -->  10K max ??
  67.    argv               -->  ?K max
  68.    ae_start frame     -->  16 bytes
  69.    ... padding  ...
  70.    top of buffer      --> @0x80000000-(32K-4K)
  71.  */
  72.  
  73. #define STACK_TOP 0x80000000
  74.  
  75.  
  76. /* Less than 32K to fit insn's 15-bit field */
  77.  
  78. #define AE_BUFFER_STACK_OFFSET 32768-4096
  79.  
  80.  
  81. /* Size of AE buffer (bytes). */
  82.  
  83. #define AE_BUFFER_SIZE 0x100000    /* 1MB */
  84.  
  85.  
  86. /* Size of a stack frame for the routine AE_START. */
  87.  
  88. #define AE_START_FRAME_SIZE (16 * sizeof (int))
  89.  
  90.  
  91. /* Name of stack pointer register. */
  92.  
  93. #define SP_REG "sp"
  94.  
  95.  
  96.  
  97. /* One plus maximum number of instructions combine by peephole optimizer. */
  98.  
  99. #define MAX_PEEP 3
  100.  
  101.  
  102. /* Return non-zero if register number REGNO can be defined upon
  103.    function entry. */
  104.  
  105. #define REGISTER_DEFINED_IN_CALL(REGNO) ((REGNO) == STACK_POINTER_REGNUM \
  106.                      || (REGNO) == FRAME_POINTER_REGNUM \
  107.                      || FUNCTION_ARG_REGNO_P ((REGNO)))
  108.  
  109.  
  110. /* Define the characters that proceed comments and assembler directives. */
  111.  
  112. #define ASM_COMMENT_CHAR '#'
  113.  
  114. #define ASM_DIRECTIVE_CHAR '.'
  115.  
  116.  
  117. /* Define the number of delayed instructions after a jump, conditional jump,
  118.    or call instruction.  Do not define these values if the instructions have
  119.    no delays or the assembler hides them by doing code reorganization. */
  120.  
  121. #undef JUMP_DELAY_SLOTS
  122.  
  123. #undef CJUMP_DELAY_SLOTS
  124.  
  125. #undef CALL_DELAY_SLOTS
  126.  
  127.  
  128. /* The size of most assembly instructions (in bytes). */
  129.  
  130. #define STD_ASM_INSN_LENGTH 4
  131.  
  132.  
  133. /* Set of instruction-size pairs for instructions whose size is not
  134.    standard.  The table must be sorted by instruction name. */
  135.  
  136. #define ASM_INSN_SIZE_EXCEPTIONS            \
  137.     "abs", (char *) 3,                \
  138.     "bge", (char *) 2,                \
  139.     "bgeu", (char *) 2,                \
  140.     "bgt", (char *) 2,                \
  141.     "bgtu", (char *) 2,                \
  142.     "ble", (char *) 2,                \
  143.     "bleu", (char *) 2,                \
  144.     "blt", (char *) 2,                \
  145.     "bltu", (char *) 2,                \
  146.     "div", (char *) 10,        /* Guess */    \
  147.     "divu", (char *) 10,        /* Guess */    \
  148.     "la", (char *) 2,                \
  149.     "li", (char *) 2,                \
  150.     "mul", (char *) 2,                \
  151.     "mulo", (char *)  5,                \
  152.     "mulou", (char *) 4,                \
  153.     "neg", (char *) 2,                \
  154.     "negu", (char *) 3,                \
  155.     "rem", (char *) 10,        /* Guess */    \
  156.     "remu", (char *) 10,        /* Guess */    \
  157.     "rol", (char *) 3,                \
  158.     "ror", (char *) 3,                \
  159.     "seq", (char *) 2,                \
  160.     "sge", (char *) 2,                \
  161.     "sgeu", (char *) 2,                \
  162.     "sgt", (char *) 2,                \
  163.     "sgtu", (char *) 2,                \
  164.     "sle", (char *) 2,                \
  165.     "sleu", (char *) 2,                \
  166.     "sne", (char *) 2,                \
  167.     "ulh", (char *) 2,                \
  168.     "ulhu", (char *) 2,                \
  169.     "ulw", (char *) 2,                \
  170.     "ush", (char *) 2,                \
  171.     "usw", (char *) 2
  172.  
  173.  
  174. /* Return non-zero if the assembly instruction is a branch that does
  175.    not execute its (normally) delayed slot instruction. */
  176.  
  177. #define BRANCH_IS_ANNULED(ASM_INSN) 0
  178.  
  179.  
  180. /* Return a pointer to the function name if an assembly instruction is
  181.    a subroutine invocation.  If it is not, return 0. */
  182.  
  183. #define ASM_INSN_IS_CALL(ASM_INSN) (strncmp ((ASM_INSN), "jal", 3) \
  184.                     ? 0 : (ASM_INSN) + 3)
  185.  
  186.  
  187.  
  188.  
  189. /* Produce the schema corresponding the the standard function prologue
  190.    and epilogue.  Record values that are need upon function entry. */
  191.  
  192. #define SCHEMA_PROLOGUE(RECORD_REG_ON_ENTRY)            \
  193. {                                \
  194.   /* Code from FUNCTION_PROLOGUE: */                \
  195.   int frame_size = get_frame_size ();                \
  196.   register int regno;                        \
  197.   register int mask = 0, fmask=0;                \
  198.   extern char call_used_regs [];                \
  199.   register int push_loc = 0, tsize = frame_size + 8;        \
  200.                                 \
  201.   for (regno = 0; regno < 32; regno++)                \
  202.     if (MUST_SAVE_REG_LOGUES                    \
  203.     || (regs_ever_live [regno] && !call_used_regs [regno]))    \
  204.       {tsize += 4; mask |= 1 << regno;}                \
  205.                                 \
  206.   for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)    \
  207.     if (regs_ever_live [regno] && !call_used_regs [regno])    \
  208.       {tsize += 8; fmask |= 1 << (regno-32);}            \
  209.                                 \
  210.   if (THIS_VARARGS_SUSPECTED) tsize += 16;            \
  211.                                 \
  212.   regno = STACK_POINTER_REGNUM;                    \
  213.   tsize = AL_ADJUST_ALIGN (tsize);                \
  214.                                 \
  215.   push_loc = 0;                            \
  216.                                 \
  217.   if (frame_pointer_needed                    \
  218.       || regs_ever_live [29] || regs_ever_live [30]        \
  219.       || fmask || mask                        \
  220.       || (frame_size > 0))                    \
  221.     record_sp ();                        \
  222.                                 \
  223.   for (regno = 31; regno >= 30; regno--)            \
  224.     if (MUST_SAVE_REG_LOGUES                    \
  225.     || (regs_ever_live [regno] && !call_used_regs [regno]))    \
  226.       {                                \
  227.     store_schema_int_offset (STACK_POINTER_REGNUM, push_loc, 0);\
  228.     push_loc += 4;                        \
  229.       }                                \
  230.                                 \
  231.   if (THIS_VARARGS_SUSPECTED)                    \
  232.     {                                \
  233.       int fregno;                        \
  234.       simple_def_schema (9, 0, tsize);                \
  235.       store_schema_int_offset (STACK_POINTER_REGNUM, tsize - 4, 0);\
  236.       for (fregno = 44; fregno< 48; fregno += 2)        \
  237.     {                            \
  238.       store_schema_int_offset (STACK_POINTER_REGNUM, push_loc, 1);\
  239.       push_loc += 8;                    \
  240.     }                            \
  241.     }                                \
  242.                                 \
  243.   for (regno = 29; regno >= 0; regno--)                \
  244.     if (MUST_SAVE_REG_LOGUES                    \
  245.     || (regs_ever_live [regno] && !call_used_regs [regno]))\
  246.       {                                \
  247.     store_schema_int_offset (STACK_POINTER_REGNUM, push_loc, 0);\
  248.     push_loc += 4;                        \
  249.       }                                \
  250.                                 \
  251.   for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)    \
  252.     if (regs_ever_live [regno] && !call_used_regs [regno])    \
  253.       {                                \
  254.     store_schema_int_offset (STACK_POINTER_REGNUM, push_loc, 1);\
  255.     push_loc += 8;                        \
  256.       }                                \
  257.                                 \
  258.   if (frame_pointer_needed)                    \
  259.     simple_def_schema (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM, tsize);\
  260.                                 \
  261.   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)    \
  262.     if (RECORD_REG_ON_ENTRY [regno]                \
  263.     && regno != STACK_POINTER_REGNUM            \
  264.     && regno != FRAME_POINTER_REGNUM)            \
  265.       {                                \
  266.     unknown_def_schema (regno);                \
  267.     issue_event (gen_rtx (REG, Pmode, regno));        \
  268.       }                                \
  269. }
  270.  
  271.  
  272. #define SCHEMA_EPILOGUE()                    \
  273. {                                \
  274.   /* Code from FUNCTION_EPILOGUE: */                \
  275.   int frame_size = get_frame_size ();                \
  276.   register int regno;                        \
  277.   register int mask = 0, fmask = 0;                \
  278.   extern char call_used_regs [];                \
  279.   register int push_loc ;                    \
  280.                                 \
  281.   extern int current_function_total_framesize;            \
  282.                                 \
  283.   push_loc = 0;                            \
  284.   regno = STACK_POINTER_REGNUM;                    \
  285.                                 \
  286.   if (frame_pointer_needed)                    \
  287.     simple_def_schema (8, FRAME_POINTER_REGNUM, 0);        \
  288.                                 \
  289.   for (regno = 0; regno < 32; regno++)                \
  290.     if (MUST_SAVE_REG_LOGUES                    \
  291.     || (regs_ever_live [regno] && !call_used_regs [regno]))    \
  292.       mask |= 1 << regno;                    \
  293.                                 \
  294.   for (regno = 31; regno >= 0; regno--)                \
  295.     {                                \
  296.       if (MUST_SAVE_REG_LOGUES                    \
  297.       || (regs_ever_live [regno] && !call_used_regs [regno]))\
  298.     {                            \
  299.       load_schema_int_offset ((frame_pointer_needed ? 8 : STACK_POINTER_REGNUM),\
  300.                (frame_pointer_needed ?            \
  301.             push_loc - current_function_total_framesize:\
  302.             push_loc),                \
  303.                0);                    \
  304.       push_loc += 4;                    \
  305.     }                            \
  306.       if (THIS_VARARGS_SUSPECTED && (regno == 30))        \
  307.     push_loc += 16;                        \
  308.     }                                \
  309.                                 \
  310.   for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)    \
  311.     if (regs_ever_live [regno] && !call_used_regs [regno])    \
  312.       fmask |= 1 <<  (regno-32);                \
  313.                                 \
  314.   for (regno = 32; regno < FIRST_PSEUDO_REGISTER; regno += 2)    \
  315.     if (regs_ever_live [regno] && !call_used_regs [regno])    \
  316.       {                                \
  317.     load_schema_int_offset ((frame_pointer_needed ? 8 : STACK_POINTER_REGNUM),\
  318.              (frame_pointer_needed ?            \
  319.               push_loc - current_function_total_framesize:\
  320.               push_loc),                \
  321.                                 \
  322.              1);                    \
  323.     push_loc += 8;                        \
  324.       }                                \
  325.                                 \
  326.   if (frame_pointer_needed)                    \
  327.     simple_def_schema (STACK_POINTER_REGNUM, 8, 0);        \
  328.   else                                \
  329.     if (regs_ever_live [29]|| regs_ever_live [30]        \
  330.     || fmask || mask                    \
  331.     ||  (frame_size > 0))                    \
  332.       simple_def_schema (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,\
  333.             current_function_total_framesize);    \
  334. }
  335.  
  336.  
  337.  
  338. /* Produce and write the the assembly output file code to record the
  339.    various types of events. */
  340.  
  341.  
  342. /* Check that the AE buffer has SIZE bytes free.  If not, empty the
  343.    buffer. */
  344.  
  345. #define GENERATE_SPACE_CHECK(COMMENT, SIZE)            \
  346. {                                \
  347.   rtx xops [1];                            \
  348.   rtx label = gen_label_rtx ();                    \
  349.   char buffer [256];                        \
  350.                                 \
  351.   sprintf (buffer, ".set noat\t\t\t\t# %s Event w/ check", COMMENT);\
  352.   output_asm_insn (buffer, xops);                \
  353.                                 \
  354.   xops [0] = ae_buffer_pointer;                    \
  355.   sprintf (buffer, "addu $1,%%0,%d", AE_BUFFER_STACK_OFFSET + CHUNK_SIZE);\
  356.   output_asm_insn (buffer, xops);                \
  357.                                 \
  358.   xops [0] = label;                        \
  359.   output_asm_insn ("bgtz $1,%l0", xops);            \
  360.   output_asm_insn (".set at", xops);                \
  361.                                 \
  362.   output_asm_insn ("jal ae_flush_buffer", xops);        \
  363.                                 \
  364.   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (label));\
  365. }
  366.  
  367.  
  368. /* Generate an event to record VALUE (an rtx register). */
  369.  
  370. #define GENERATE_EVENT(VALUE)                    \
  371. {                                \
  372.   rtx xops [2];                            \
  373.                                 \
  374.   xops [0] = VALUE;                        \
  375.   xops [1] = ae_buffer_pointer;                    \
  376.   output_asm_insn ("usw\t%0,0(%1)", xops);            \
  377.                                 \
  378.   xops [0] = ae_buffer_pointer;                    \
  379.   output_asm_insn ("addiu\t%0,%0,4\t\t# End Event", xops);    \
  380. }
  381.  
  382.  
  383. /* Generate an event to record the integer VALUE, which should be
  384.    stored in BYTES bytes. */
  385.  
  386. #define GENERATE_SHORT_EVENT(VALUE, BYTES)            \
  387. {                                \
  388.   rtx xops [2];                            \
  389.                                 \
  390.   output_asm_insn (".set noat", xops);                \
  391.   xops [0] = gen_rtx (CONST_INT, VOIDmode, VALUE);        \
  392.   output_asm_insn ("addiu\t$1,$0,%0", xops);            \
  393.                                 \
  394.   xops [0] = ae_buffer_pointer;                    \
  395.   if (BYTES == 1)                        \
  396.     output_asm_insn ("sb\t$1,0(%0)", xops);            \
  397.   else                                \
  398.     output_asm_insn ("ush\t$1,0(%0)", xops);            \
  399.   output_asm_insn (".set at", xops);                \
  400.                                 \
  401.   xops [0] = ae_buffer_pointer;                    \
  402.   xops [1] = gen_rtx (CONST_INT, VOIDmode, BYTES);        \
  403.   output_asm_insn ("addiu\t%0,%0,%1\t\t# End Short Event", xops);\
  404. }
  405.  
  406.  
  407. /* Generate an event to record ADDRESS, which is made computed from BASE and
  408.    OFFSET. */
  409.  
  410. #define GENERATE_ADDRESS_EVENT(ADDRESS, BASE, OFFSET)        \
  411. {                                \
  412.   rtx xops [1];                            \
  413.                                 \
  414.   output_asm_insn (".set noat", xops);                \
  415.   xops [0] = ADDRESS;                        \
  416.   /* Causes assembler warning since LA is a macro, but produces    \
  417.      correct code. */                        \
  418.   output_asm_insn ("la\t$1,%0", xops);                \
  419.                                 \
  420.   xops [0] = ae_buffer_pointer;                    \
  421.   output_asm_insn ("usw\t$1,0(%0)", xops);            \
  422.   output_asm_insn (".set at", xops);                \
  423.                                 \
  424.   xops [0] = ae_buffer_pointer;                    \
  425.   output_asm_insn ("addiu\t%0,%0,4\t\t# End Address Event", xops);\
  426. }
  427.  
  428.  
  429.  
  430. /* Assembly code routines for aecrt0.o. */
  431.  
  432. #ifdef AE_START_ASM
  433.     .align 2
  434.     .globl ae_start
  435.     .ent ae_start
  436. ae_start:
  437.     .set nomove        /* Do not allow the assembler to move insns.*/
  438.     lw    $4,0($sp)
  439.     la    $gp,_gp
  440.     addiu    $5,$sp,4
  441.     addiu    $6,$5,4
  442.     sll    $2,$4,2
  443.     addu    $6,$6,$2
  444.     addiu    $sp,$sp,-24
  445.     sw    $0,20($sp)
  446.     sw    $6,environ
  447.     sw    $5,__Argv
  448.     sw    $4,__Argc
  449.     sw    $0,errno
  450.     jal    ae_initialize    /* Addition */
  451.     lw    $5,__Argv    /* ditto */
  452.     lw    $4,__Argc    /* ditto */
  453.     jal    main
  454.     jal    exit
  455.     move    $4,$2
  456.     break    0
  457.     .set move
  458.     .end ae_start
  459. #endif
  460.  
  461.  
  462. #ifdef AE_FLUSH_BUFFER_ASM
  463.     .align 2
  464.     .globl ae_flush_buffer
  465.     .ent    ae_flush_buffer
  466. ae_flush_buffer:
  467.  /*PROLOGUE */
  468.  /*    .mask    0xc0010000 */
  469.     subu    $29,152    /*temp=  128,saveregs=   24, sfo=   -8 */
  470.     sw    $31,0($29)
  471.     sw    $30,4($29)
  472.     sw    $16,8($29)
  473.  /*    .fmask    0x0 */
  474.     addiu    $30,$29,152    /*Establish FramePTR */
  475.  /*END PROLOGUE */
  476.     .set noat
  477.     addiu    $16,$30,0xff78    /*addsi3    $30,-136 -> $16 */
  478.     sw $1,4($16)
  479.     .set at
  480.     sw $2,8($16)
  481.     sw $3,12($16)
  482.     sw $4,16($16)
  483.     sw $5,20($16)
  484.     sw $6,24($16)
  485.     sw $7,28($16)
  486.     sw $8,32($16)
  487.     sw $9,36($16)
  488.     sw $10,40($16)
  489.     sw $11,44($16)
  490.     sw $12,48($16)
  491.     sw $13,52($16)
  492.     sw $14,56($16)
  493.     sw $15,60($16)
  494.     sw $17,68($16)
  495.     sw $18,72($16)
  496.     sw $19,76($16)
  497.     sw $20,80($16)
  498.     sw $21,84($16)
  499.     sw $22,88($16)
  500.     sw $24,96($16)
  501.     sw $25,100($16)
  502.     sw $26,104($16)
  503.     sw $27,108($16)
  504.     sw $28,112($16)
  505.     addiu    $29,$29,0xfff0    /*subsi3    $29,16 -> $29 */
  506.     lw    $4,ae_fd    /*movsi ae_fd -> $4 */
  507.     lw    $5,ae_buffer_base    /*movsi ae_buffer_base -> $5 */
  508.     subu    $6,$23,$5    /*subsi3 $23,$5 -> $6 */
  509.     jal    write    /* call  write  regle 2-call (VOIDmode) */
  510.     lw    $23,ae_buffer_base    /*movsi ae_buffer_base -> $23 */
  511.     .set noat
  512.     lw $1,4($16)
  513.     .set at
  514.     lw $2,8($16)
  515.     lw $3,12($16)
  516.     lw $4,16($16)
  517.     lw $5,20($16)
  518.     lw $6,24($16)
  519.     lw $7,28($16)
  520.     lw $8,32($16)
  521.     lw $9,36($16)
  522.     lw $10,40($16)
  523.     lw $11,44($16)
  524.     lw $12,48($16)
  525.     lw $13,52($16)
  526.     lw $14,56($16)
  527.     lw $15,60($16)
  528.     lw $17,68($16)
  529.     lw $18,72($16)
  530.     lw $19,76($16)
  531.     lw $20,80($16)
  532.     lw $21,84($16)
  533.     lw $22,88($16)
  534.     lw $24,96($16)
  535.     lw $25,100($16)
  536.     lw $26,104($16)
  537.     lw $27,108($16)
  538.     lw $28,112($16)
  539.     addiu    $29,$29,0x10    /*addsi3    $29,16 -> $29 */
  540.  /*EPILOGUE */
  541.     addu    $29,$0,$30    /* sp not trusted  here */
  542.  /*    .mask    0xc0010000 */
  543.     lw    $31,-152($29)
  544.     lw    $30,-148($29)
  545.     lw    $16,-144($29)
  546.  /*    .fmask    0x0 */
  547.     j    $31
  548.  /*END EPILOGUE */
  549.      .end    ae_flush_buffer
  550.     .comm    ae_fd,8
  551.     .comm    ae_buffer_base,8
  552. #endif
  553.  
  554.  
  555.  
  556. /* Definitions for AEC. */
  557.  
  558. /* a.out file format is ECOFF, with the LDFCN library to find symbols. */
  559.  
  560. #define ECOFF_AOUT
  561. #undef BSD_AOUT
  562.  
  563.  
  564. /* Function call returns this many bytes after call instruction. */
  565.  
  566. /* We don't see delayed instructions on MIPS, so return to the next
  567.    instruction.*/
  568.  
  569. #define PC_OFFSET_AFTER_CALL 4
  570.  
  571.  
  572. /* Return non-zero if register N is local to a function, e.g. can
  573.    have distinct values in different functions. */
  574.  
  575. #define REG_LOCAL_TO_FUNCTION(N) (!call_used_regs [(N)]        \
  576.                   || (N) == STACK_POINTER_REGNUM)
  577.  
  578.  
  579. /* Initialize registers before the generation program begins. */
  580.  
  581. #define INITIALIZE_REGISTERS()                    \
  582.     {                            \
  583.       char buf [80];                    \
  584.       output_set_value (0, "0");                \
  585.       sprintf (buf, "0x%x", symbol_address_or_die ("_gp"));    \
  586.       output_set_value (28, buf);                \
  587.     }
  588.